﻿#region Copyright (c) Lokad 2010
// This code is released under the terms of the new BSD licence.
// URL: http://www.lokad.com/
#endregion
using System;
using System.Web;
using Autofac;
using Autofac.Builder;
using Autofac.Integration.Web;
using FluentNHibernate.Automapping;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using Lokad.Monitoring.Persistence.Entities;
using Lokad.Monitoring.Repositories;
using Microsoft.WindowsAzure.ServiceRuntime;
using NHibernate;
using NHibernate.ByteCode.Castle;
using NHibernate.Cfg;

namespace Lokad.Monitoring
{
    public static class GlobalSetup
    {
        // public because it's needed in the web app for ELMAH (not setup yet)
        public static string ConnectionString
        {
            get
            {
                return RoleEnvironment.IsAvailable ?
                    RoleEnvironment.GetConfigurationSettingValue("SqlConnectionString") :
                    System.Configuration.ConfigurationManager.ConnectionStrings["SqlServices"].ConnectionString;
            }
        }

        static IContainerProvider _containerProvider;

        static IContainer SetUp()
        {
            var builder = new ContainerBuilder();

            builder.Register(context =>
            {
                var model = AutoMap.AssemblyOf<User>()
                    .Where(t => t.Namespace == "Lokad.Monitoring.Persistence.Entities");

                var config = Fluently.Configure()
                    .Database(MsSqlConfiguration.MsSql2008
                        .ConnectionString(c => c.Is(ConnectionString)))
                    .Mappings(m => m.AutoMappings.Add(model))
                    .ExposeConfiguration(ConfigProxy);

                return config.BuildSessionFactory();
            }).SingletonScoped();

            builder.Register(c =>
            {
                var session = c.Resolve<ISessionFactory>().OpenSession();
                session.FlushMode = FlushMode.Commit;
                return session;
            }).ContainerScoped();

            builder.RegisterModule(new RepositoriesModule());

            return builder.Build();
        }

        // HACK: work-around an issue caused by NHibernate being wrapped into Lokad.Data
        static void ConfigProxy(Configuration obj)
        {
            obj.Properties["proxyfactory.factory_class"] = typeof(ProxyFactoryFactory).FullName;
            //obj.Properties["use_proxy_validator"] = "false";
        }

        /// <summary>Indicates whether the current application is an ASP.NET application.</summary>
        public static bool IsAspNetApplication
        {
            get
            {
                return HttpContext.Current != null;
            }
        }

        /// <summary>Gets the IoC container as initialized by the setup.</summary>
        /// <remarks>Automatically handles ASP.NET applications.</remarks>
        public static IContainer Container
        {
            get
            {
                if (null == _containerProvider)
                {
                    _containerProvider = new ContainerProvider(SetUp());
                }

                return IsAspNetApplication ? 
                    _containerProvider.RequestContainer : 
                    _containerProvider.ApplicationContainer;
            }
        }

        /// <summary>Disposes the current request container.</summary>
        public static void DisposeRequestContainer()
        {
            if (!IsAspNetApplication) throw new InvalidOperationException("The current application is not an ASP.NET application");

            if (_containerProvider != null) _containerProvider.DisposeRequestContainer();
        }
    }
}
